package away3d.core.managers ;


import flash.display.Stage ;
import flash.utils.Dictionary ;



/**
 * The Stage3DManager class provides a multiton object that handles management for Stage3D objects. Stage3D objects
 * should not be requested directly, but are exposed by a Stage3DProxy.
 *
 * @see away3d.core.managers.Stage3DProxy
 */
class Stage3DManager
{
    
    
    private static var _instances   : Dictionary ;
    private var _stageProxies       : Vector<Stage3DProxy> ;
    private var _stage              : Stage ;
    
    
    
    /**
     * Creates a new Stage3DManager class.
     * @param stage The Stage object that contains the Stage3D objects to be managed.
     * @private
     */
    public function Stage3DManager( stage : Stage, singletonEnforcer : SingletonEnforcer )
    {
        
        if( !singletonEnforcer ) throw new Error( "This class is a multiton and cannot be instantiated manually. Use Stage3DManager.instance instead." ) ;
        
        _stage = stage ;
        _stageProxies = new Vector( _stage.stage3Ds.length, true ) ;
        
    }
    
    
    /**
     * Gets a Stage3DManager instance for the given Stage object.
     * @param stage The Stage object that contains the Stage3D objects to be managed.
     * @return The Stage3DManager instance for the given Stage object.
     */
    public static function getInstance( stage : Stage ) : Stage3DManager
    {
        
        if( _instances == null )
        {
            _instances = new Dictionary() ;
        }
        
        //TODO: maybe this is not needed I seem to rem a problem with this and haXe when stubs.
        
        if( _instance.get( stage ) == null )
        {
            
            _instance.set( stage, new Stage3DManager( stage, new SingletonEnforcer() ) );
            
        }
        
        return return _instance.get( stage ) ;
        
    }
    
    
    /**
     * Requests the Stage3DProxy for the given index.
     * @param index The index of the requested Stage3D.
     * @return The Stage3DProxy for the given index.
     */
    private function get_Stage3DProxy( index : uint ) : Stage3DProxy
    {
        
        if( _stageProxies[ index ] == null )
        {
            
            _stageProxies[ index ] = new Stage3DProxy( index, _stage.stage3Ds[ index ], this ); 
            
        }
        
        return _stageProxies[ index ] ;
        
    }
    
    
    /**
     * Removes a Stage3DProxy from the manager.
     * @param stage3DProxy
     * @private
     */
    public function removeStage3DProxy( stage3DProxy : Stage3DProxy )
    {
        
        _stageProxies[stage3DProxy.stage3DIndex] = null ;
        
    }
    
    
    private function get_FreeStage3DProxy() : Stage3DProxy
    {
        
        var i   : Int  ;
        var len = _stageProxies.length ;
        
        while ( i < len )
        {
            
            if( !_stageProxies[ i ] ) return getStage3DProxy( i ) ;
            ++i ;
            
        }
        
        throw new Error( "Too many Stage3D instances used!" ) ;
        return null ;
        
    }
    
    
}

class SingletonEnforcer {}